<?php


namespace App\Api\V1\Services\Wechat;


use App\Api\V1\Exceptions\Wechat\WechatException;
use App\Commons\WechatOpenPlatform\WechatOpenPlatformTool;
use App\Http\Middleware\TerminateTask;
use App\Models\App\AppProject;
use App\Models\Wechat\MiniProgramOperationRecord;
use App\Repositories\App\AppProjectRepository;
use App\Repositories\Wechat\MiniProgramOperationRecordRepository;
use Illuminate\Support\Facades\Log;

class WechatService {
    /**
     * 授权回调处理
     *
     * @param $appProjectId
     * @param $wxAuthCode
     *
     * @throws WechatException
     */
    public function getAuthInfo($appProjectId, $wxAuthCode) {
        //Log::info('本地项目id:' . $appProjectId);
        //Log::info('auth code 返回值:' . $wxAuthCode);
        
        $authResultInfo = WechatOpenPlatformTool::getInstance()->handleAuthorize($wxAuthCode);
        
        //Log::info('授权信息获取结果');
        //Log::info($authResultInfo);
        
        if (isset($authResultInfo['authorization_info'])) {
            $authTime = date('Y-m-d H:i:s');
            //获取授权小程序信息
            $authorizerInfo = WechatOpenPlatformTool::getInstance()->getAuthorizer($authResultInfo['authorization_info']['authorizer_appid']);
            //Log::info('授权应用信息:');
            //Log::info($authorizerInfo);
            
            if (!isset($authorizerInfo['authorizer_info'])) {
                Log::error('获取授权方的帐号基本信息失败：' . $appProjectId);
                Log::error($authorizerInfo);
                throw new WechatException(1010003);
            }
            
            //记录授权信息
            $appProjectEl = AppProjectRepository::getInstance()->update(
                $appProjectId,
                [
                    'wx_authorizer_appid'         => $authResultInfo['authorization_info']['authorizer_appid'],
                    'wx_authorizer_refresh_token' => $authResultInfo['authorization_info']['authorizer_refresh_token'],
                    'open_appid'                  => WechatOpenPlatformTool::getOpenPlatformConfig()['app_id'],
                    'auth_time'                   => $authTime,
                    'auth_status'                 => \App\Models\App\AppProject::AUTH_STATUS_YES,
                    'wx_nick_name'                => $authorizerInfo['authorizer_info']['nick_name'],
                    'wx_head_img'                 => $authorizerInfo['authorizer_info']['head_img'],
                    'wx_verify_type_info_id'      => $authorizerInfo['authorizer_info']['verify_type_info']['id'],
                    'wx_user_name'                => $authorizerInfo['authorizer_info']['user_name'],
                    'wx_principal_name'           => $authorizerInfo['authorizer_info']['principal_name'],
                    'wx_signature'                => $authorizerInfo['authorizer_info']['signature'],
                    'wx_qrcode_url'               => $authorizerInfo['authorizer_info']['qrcode_url'],
                ],
                null,
                new WechatException(1010001)
            );
    
            unset($authResultInfo['authorization_info']['authorizer_refresh_token']);
            unset($authResultInfo['authorization_info']['authorizer_access_token']);
    
            //操作记录日志
            TerminateTask::addTaskFnList(function () use ($appProjectEl, $authResultInfo) {
                $this->_eventDealWeappAuditRecordStore('项目授权绑定成功', $appProjectEl, $authResultInfo, MiniProgramOperationRecord::OP_RESULT_SUCCESS);
            });
    
            //服务器域名设置
            TerminateTask::addTaskFnList(function () use ($appProjectEl) {
                self::getMiniProgramToolByProjectEl($appProjectEl)->domainModify($appProjectEl->serverDomainWithTypeAndTemplate() + ['action' => 'set']);
            });
    
            //业务域名同步
            TerminateTask::addTaskFnList(function () use ($appProjectEl) {
                self::getMiniProgramToolByProjectEl($appProjectEl)->setWebviewDomain($appProjectEl->webviewdomainWithTypeAndTemplate(), 'set');
            });
    
        } else {
            Log::error('小程序授权失败：' . $appProjectId);
            Log::error($authResultInfo);
            throw new WechatException(1010002);
        }
    }
    
    /**
     * @param $payload
     */
    public function eventDeal($appId, $payload) {
        $event           = $payload['Event'];
        $projectElCol    = AppProjectRepository::getInstance()->getProjectByAppId($appId);
    
        foreach ($projectElCol as $projectEl) {
            switch ($event) {
                case 'weapp_audit_success' : //代码提交审核成功
                    $this->_eventDealWeappAuditRecordStore('代码提交审核成功', $projectEl, $payload, MiniProgramOperationRecord::OP_RESULT_SUCCESS);
                    $projectEl->last_audit_status = AppProject::LAST_AUDIT_STATUS_SUCCESS;
                    $projectEl->save();
                    //发布代码
                    if ($projectEl->switch_audit_success_release == AppProject::SWITCH_AUDIT_SUCCESS_RELEASE_ON) {
                        $miniProgramTool = WechatOpenPlatformTool::getInstance()->getMiniProgramTool($appId, $projectEl->wx_authorizer_refresh_token, $projectEl);
                        $miniProgramTool->release();
                    }
                    
                    break;
                case 'weapp_audit_fail' : //代码审核不通过
                    $projectEl->last_audit_status = AppProject::LAST_AUDIT_STATUS_FAIL;
                    $projectEl->save();
                    $this->_eventDealWeappAuditRecordStore('代码审核不通过', $projectEl, $payload, MiniProgramOperationRecord::OP_RESULT_FAIL);
                    break;
                case 'weapp_audit_delay' : //代码提交审核延后
                    $projectEl->last_audit_status = AppProject::LAST_AUDIT_STATUS_DELAY;
                    $projectEl->save();
                    $this->_eventDealWeappAuditRecordStore('代码提交审核延后', $projectEl, $payload, MiniProgramOperationRecord::OP_RESULT_FAIL);
                    break;
                default:
                    break;
            }
        }
    }
    
    /**
     * 记录小程序操作
     *
     * @param $opName
     * @param $projectEl
     * @param $payload
     * @param $opResult
     */
    protected function _eventDealWeappAuditRecordStore($opName, $projectEl, $payload, $opResult) {
        $operationData = [
            'ap_id'               => $projectEl->id,
            'open_appid'          => $projectEl->open_appid,
            'wx_authorizer_appid' => $projectEl->wx_authorizer_appid,
            'op_name'             => $opName,
            'result'              => json_encode($payload),
            'op_result'           => $opResult,
            'mpt_id'              => $projectEl->mpt_id,
        ];
        
        MiniProgramOperationRecordRepository::getInstance()->store($operationData);
    }
    
    /**
     * 授权成功处理
     *
     * @param $payload
     */
    public function authorized($payload) {
        $projectElCol = AppProjectRepository::getInstance()->getProjectByAppId($payload['AuthorizerAppid']);
        
        unset($payload['AuthorizationCode']);
        foreach ($projectElCol as $projectEl) {
            $this->_eventDealWeappAuditRecordStore('授权成功通知', $projectEl, $payload, MiniProgramOperationRecord::OP_RESULT_SUCCESS);
        }
    }
    
    /**
     * 授权更新通知
     *
     * @param $payload
     *
     * @throws \Exception
     */
    public function updateAuthorized($payload) {
        $projectElCol = AppProjectRepository::getInstance()->getProjectByAppId($payload['AuthorizerAppid']);
        
        $authorizationCode = $payload['AuthorizationCode'];
    
        unset($payload['AuthorizationCode'], $payload['PreAuthCode']);//去除敏感信息
    
        foreach ($projectElCol as $projectEl) {
            $this->_eventDealWeappAuditRecordStore('授权更新通知', $projectEl, $payload, MiniProgramOperationRecord::OP_RESULT_SUCCESS);
    
            //重新获取授权信息,利用 授权码，可用于获取授权信息，refresh_token 重新获取
            //https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/api/authorize_event.html
            //https://developers.weixin.qq.com/miniprogram/dev/devtools/ext.html#%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%A8%A1%E6%9D%BF%E5%BC%80%E5%8F%91
    
            $this->getAuthInfo($projectEl->id, $authorizationCode);
        }
    }
    
    /**
     * 取消授权通知
     *
     * @param $payload
     */
    public function unauthorized($payload) {
        $projectElCol = AppProjectRepository::getInstance()->getProjectByAppId($payload['AuthorizerAppid']);
    
        foreach ($projectElCol as $projectEl) {
            $this->_eventDealWeappAuditRecordStore('取消授权通知', $projectEl, $payload, MiniProgramOperationRecord::OP_RESULT_SUCCESS);
    
            //修改授权状态
            $projectEl->auth_status = AppProject::AUTH_STATUS_NO;
            $projectEl->save();
        }
    }
    
    /**
     * @param $projectEl
     *
     * @return \App\Commons\WechatOpenPlatform\WechatOpenPlatformMiniProgramTool
     */
    public static function getMiniProgramToolByProjectEl($projectEl) {
        return WechatOpenPlatformTool::getInstance()
            ->getMiniProgramTool($projectEl->wx_authorizer_appid, $projectEl->wx_authorizer_refresh_token, $projectEl);
    }
}